/**
 * 
 */
package problem4;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;

//arbeitet Warteschlange ab
public class Cashpoint implements Runnable {

	private CopyOnWriteArrayList<Customer> customers = new CopyOnWriteArrayList<Customer>();

	private boolean open = false;

	private String name;

	private int id;

	private List<Cashpoint> cashpoints;

	public Cashpoint(String name, int id, List<Cashpoint> cashpoints) {
		this.name = name;
		this.id = id;
		this.cashpoints = cashpoints;
	}

	@Override
	public void run() {

		// Die Öffnung einer Kasse dauert 6 Sekunden
		try {
			Thread.sleep((int) 6000);
		} catch (InterruptedException e) {
		}

		System.out.println(this.name + " geöffnet!");

		// Durchlaufen solange die Kasse geöffnet ist
		while (open) {

			// intrinsischer Lock
			// Weiterer customers-Lock beim Aquirieren von Kunden
			// Lock nötig, damit sich z.B. keine Kunden an zu schließender Kasse anstellen
			synchronized (customers) {			

				// Ersten Kunden aus der Warteschlange entfernen
				System.out.println(this.name + " arbeitet " + customers.get(0).getName() + " ab.");
				Balance.getInstance().setEntry(id);
				
				// intrinsischer Lock
				// Weiterer cashpoints-Lock beim Suchen der kürzesten Kasse/Eröffnen einer neuen Kasse
				synchronized (cashpoints) {					
					customers.remove(0);
				}
				// Wenn keine Customers in der Liste sind, dann Kasse vorübergehend schließen
				if (customers.size() == 0) {
					System.out.println(this.name + " wird geschlossen!");
					open = false; // Keine Kunden, die sich an leerer Kasse anstellen, weil open überprüft wird
				}

			}

			// Abarbeitung eines Kunden dauert 6-10 Sekunden
			// Streng genommen müsste es in den geschützten Bereich.
			// Ist so okay. -> geklärt mit Manuel
			try {
				Random random = new Random();
				Thread.sleep((int) (random.nextDouble() * 4001 + 6000));
			} catch (InterruptedException e) {

			}

		}

	}

	public void addCustomer(Customer customer) {
		customers.add(customer);
	}

	public CopyOnWriteArrayList<Customer> getCustomers() {
		return customers;
	}

	public void setCustomers(CopyOnWriteArrayList<Customer> customers) {
		this.customers = customers;
	}

	public boolean isOpen() {
		return open;
	}

	public void setOpen(boolean open) {
		this.open = open;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
